/**
 * Implementacion de la clase Map.
 */
#include "map.hpp"
#include "../list/listIterator.hpp"
#include "../validacion/mapObjectValidator.hpp"
#include "../config/config.hpp"

void Map::init()
{
	Node		  *nodeTemp = NULL;
	Edge		  *edgeTemp = NULL;
		
	ListIterator<Node> nodeIt = this->graph->getNodes()->iterator();
	while(nodeIt.hasNext())
	{
		nodeTemp = nodeIt.next();
		//Agrego el cruce al mapa
		this->addMapIntersection(MapIntersection::generateMapIntersection(nodeTemp));

		ListIterator<Edge> edgeIt = nodeTemp->getEdgeList()->iterator();
		while(edgeIt.hasNext())
		{
			edgeTemp = edgeIt.next();
			//Agrego las calles;
			this->addMapStreet(MapStreet::generateMapStreet(edgeTemp,this->graph));
		}
	}
	std::string fileToParse = Config::getInstance()->get("mapobject_txt_path");
	if(!fileToParse.empty())
	{
		MapObjectValidator mov(fileToParse,this->logger,this);
		mov.validate();
	}
	else
		this->logger->reportErrorMessage("Map","create","No se encontro el archivo de objetos de mapa");

}

void Map::evaluateMapBounds(MapElement *me)
{
	if((this->top == NULL)&&(this->bottom == NULL)&&
	   (this->left == NULL)&&(this->right == NULL))
	{
		this->top	= me;
		this->bottom= me;
		this->left	= me;
		this->right = me;
	}
	else
	{
		if(this->left->comparePositionX(me) > 0)
			this->left = me;

		if(this->top->comparePositionY(me) > 0)
			this->top = me;

		if(this->bottom->comparePositionY(me) < 0)
			this->bottom = me;

		if(this->right->comparePositionX(me) < 0)
			this->right = me;
	}
}

void Map::calculateMapBounds()
{
	this->setMapWidth((this->right->getPositionX() - this->left->getPositionX()) + atoi(Config::getInstance()->get("map_addition_x").c_str()));
	this->setMapHeight((this->bottom->getPositionY() - this->top->getPositionY()) + atoi(Config::getInstance()->get("map_addition_y").c_str()));
	std::string detail = "Mapa creado con las dimensiones, w = ";
	
	char buffer[20];
	itoa(this->getMapWidth(),buffer,10);
	detail += buffer;
	detail += ", h = ";

	itoa(this->getMapHeight(),buffer,10);
	detail += buffer;
	this->logger->reportWarningMessage("Map","calculateMapBounds",detail);
}

void Map::create(Graph *g,Logger *log)
{
	this->graph = g;
	this->logger = log;
	this->top	= NULL;
	this->bottom= NULL;
	this->left	= NULL;
	this->right = NULL;
	this->init();
	this->calculateMapBounds();
}

void Map::addMapObject(MapObject *mo)
{
	this->objects.add(mo);
}

void Map::addMapStreet(MapStreet *ms)
{
	this->streets.add(ms);
}

void Map::addMapIntersection(MapIntersection *mi)
{
	this->evaluateMapBounds(mi);
	this->intersections.add(mi);
}

MapObject* Map::getMapObject(std::string id)
{
	MapObject moTemp(id," ",0,HOSPITAL);
	return ((MapObject*)this->objects.search(&moTemp));
}

MapStreet* Map::getMapStreet(std::string id)
{
	MapStreet msTemp(id);
	return ((MapStreet*)this->streets.search(&msTemp));
}

MapIntersection* Map::getMapIntersection(std::string id)
{
	MapIntersection miTemp(id);
	return ((MapIntersection*)this->intersections.search(&miTemp));
}

List<MapElement>* Map::getMapObjects()
{
	return &(this->objects);
}

List<MapElement>* Map::getMapStreets()
{
	return &(this->streets);
}

List<MapElement>* Map::getMapIntersections()
{
	return &(this->intersections);
}

int Map::getMapWidth()
{
	return this->mapWidth;
}
int Map::getMapHeight()
{
	return this->mapHeight;
}
void Map::setMapWidth(int w)
{
	this->mapWidth = w;
}
void Map::setMapHeight(int h)
{
	this->mapHeight = h;
}
int Map::getMostLeftPositionX()
{
	 if(this->left->getPositionX()<=50)
	 {
		 return abs(this->left->getPositionX())+(atoi(Config::getInstance()->get("map_addition_x").c_str())/2);
	 }
	 return 0;

}
int Map::getMostTopPositionY()
{
	if(this->top->getPositionY()<=50)
	{
		return abs(this->top->getPositionY())+(atoi(Config::getInstance()->get("map_addition_y").c_str())/2);
	}
	return 0;
}